package httpclient

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Curl 封装HTTP请求工具
type Curl struct {
	client  *http.Client
	headers map[string]string
	cookies []*http.Cookie
	timeout time.Duration
}

// NewCurl 创建一个新的Curl实例
func NewCurl() *Curl {
	return &Curl{
		client:  &http.Client{},
		headers: make(map[string]string),
	}
}

// SetTimeout 设置请求超时时间
func (c *Curl) SetTimeout(timeout time.Duration) *Curl {
	c.timeout = timeout
	c.client.Timeout = timeout
	return c
}

// SetHeader 设置请求头
func (c *Curl) SetHeader(key, value string) *Curl {
	c.headers[key] = value
	return c
}

// SetHeaders 批量设置请求头
func (c *Curl) SetHeaders(headers map[string]string) *Curl {
	for k, v := range headers {
		c.headers[k] = v
	}
	return c
}

// SetCookie 设置Cookie
func (c *Curl) SetCookie(cookie *http.Cookie) *Curl {
	c.cookies = append(c.cookies, cookie)
	return c
}

// Get 发送GET请求
func (c *Curl) Get(url string, queryParams map[string]string) (*Response, error) {
	return c.Do("GET", url, queryParams, nil)
}

// Post 发送POST请求
func (c *Curl) Post(url string, body interface{}) (*Response, error) {
	return c.Do("POST", url, nil, body)
}

// Put 发送PUT请求
func (c *Curl) Put(url string, body interface{}) (*Response, error) {
	return c.Do("PUT", url, nil, body)
}

// Delete 发送DELETE请求
func (c *Curl) Delete(url string) (*Response, error) {
	return c.Do("DELETE", url, nil, nil)
}

// Do 执行HTTP请求
func (c *Curl) Do(method, rawURL string, queryParams map[string]string, body interface{}) (*Response, error) {
	// 解析URL
	u, err := url.Parse(rawURL)
	if err != nil {
		return nil, fmt.Errorf("parse url error: %v", err)
	}

	// 添加查询参数
	if queryParams != nil {
		q := u.Query()
		for k, v := range queryParams {
			q.Add(k, v)
		}
		u.RawQuery = q.Encode()
	}

	// 准备请求体
	var reqBody io.Reader
	if body != nil {
		switch v := body.(type) {
		case string:
			reqBody = strings.NewReader(v)
		case []byte:
			reqBody = bytes.NewReader(v)
		default:
			jsonData, err := json.Marshal(v)
			if err != nil {
				return nil, fmt.Errorf("marshal body error: %v", err)
			}
			reqBody = bytes.NewReader(jsonData)
			if _, ok := c.headers["Content-Type"]; !ok {
				c.headers["Content-Type"] = "application/json"
			}
		}
	}

	// 创建请求
	req, err := http.NewRequest(method, u.String(), reqBody)
	if err != nil {
		return nil, fmt.Errorf("create request error: %v", err)
	}

	// 设置请求头
	for k, v := range c.headers {
		req.Header.Set(k, v)
	}

	// 设置Cookie
	for _, cookie := range c.cookies {
		req.AddCookie(cookie)
	}

	// 发送请求
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("do request error: %v", err)
	}

	return &Response{resp}, nil
}

// Response 封装HTTP响应
type Response struct {
	*http.Response
}

// JSON 将响应体解析为JSON
func (r *Response) JSON(v interface{}) error {
	defer r.Body.Close()
	return json.NewDecoder(r.Body).Decode(v)
}

// Text 获取响应文本
func (r *Response) Text() (string, error) {
	defer r.Body.Close()
	data, err := io.ReadAll(r.Body)
	if err != nil {
		return "", err
	}
	return string(data), nil
}

// Bytes 获取响应字节
func (r *Response) Bytes() ([]byte, error) {
	defer r.Body.Close()
	return io.ReadAll(r.Body)
}

// IsOK 检查请求是否成功(状态码200-299)
func (r *Response) IsOK() bool {
	return r.StatusCode >= 200 && r.StatusCode < 300
}

// CheckStatus 检查状态码是否为指定值
func (r *Response) CheckStatus(status int) error {
	if r.StatusCode != status {
		return fmt.Errorf("unexpected status code: %d", r.StatusCode)
	}
	return nil
}

// ExampleUsage 示例用法(实际使用时可以删除)
func ExampleUsage() {
	// 创建客户端
	client := NewCurl().SetTimeout(10 * time.Second)

	// 设置Headers
	client.SetHeader("Authorization", "Bearer token123")
	client.SetHeader("Content-Type", "application/json")

	// GET请求
	resp, err := client.Get("https://api.example.com/users", map[string]string{
		"page":  "1",
		"limit": "10",
	})
	if err != nil {
		// 处理错误
	}

	// 解析JSON响应
	var users []map[string]interface{}
	if err := resp.JSON(&users); err != nil {
		// 处理错误
	}

	// POST请求
	user := map[string]interface{}{
		"name":  "John Doe",
		"email": "john@example.com",
	}
	resp, err = client.Post("https://api.example.com/users", user)
	if err != nil {
		// 处理错误
	}

	// 检查状态码
	if err := resp.CheckStatus(http.StatusCreated); err != nil {
		// 处理错误
	}
}
